<template>
  <el-popover
    v-model:visible="popoverVisible"
    trigger="manual"
    :placement="placement"
    :width="width"
    :teleported="true"
    :virtual-ref="virtualElement"
    virtual-triggering
    :enterable="true"
    :hide-after="0"
    :popper-class="popperClass"
  >
    <template #default>
      <div class="popover-content" @mouseenter="handlePopoverEnter" @mouseleave="handlePopoverLeave">
        <slot name="content" :row-data="currentRowData">
          <!-- 默认内容展示 -->
          <div v-for="(value, key) in filteredRowData" :key="key" class="popover-item">
            <span class="item-label">{{ key }}:</span>
            <span class="item-value">{{ value || '-' }}</span>
          </div>
        </slot>
      </div>
    </template>
  </el-popover>
</template>

<script setup>
import { ref, reactive, computed } from 'vue'

const props = defineProps({
  // 控制哪些列显示悬浮框
  showColumns: {
    type: Array,
    default: () => []
  },
  // 控制哪些字段在悬浮框中显示
  showFields: {
    type: Array,
    default: () => []
  },
  // popover 配置
  placement: {
    type: String,
    default: 'right'
  },
  width: {
    type: Number,
    default: 300
  },
  popperClass: {
    type: String,
    default: 'my-popover'
  }
})

const popoverVisible = ref(false)
const currentRowData = ref({})
const virtualElement = reactive({
  getBoundingClientRect: () => ({
    width: 0,
    height: 0,
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    x: 0,
    y: 0
  })
})

// 过滤后的行数据
const filteredRowData = computed(() => {
  if (props.showFields.length === 0) return currentRowData.value

  return Object.fromEntries(Object.entries(currentRowData.value).filter(([key]) => props.showFields.includes(key)))
})

// 处理鼠标进入 popover
const handlePopoverEnter = () => {
  popoverVisible.value = true
}

// 处理鼠标离开 popover
const handlePopoverLeave = event => {
  const { clientX, clientY } = event
  const popoverEl = document.querySelector('.my-popover')

  if (popoverEl) {
    const popoverRect = popoverEl.getBoundingClientRect()
    // 检查鼠标是否真的离开了 popover 区域
    if (
      !(
        clientX >= popoverRect.left &&
        clientX <= popoverRect.right &&
        clientY >= popoverRect.top &&
        clientY <= popoverRect.bottom
      )
    ) {
      popoverVisible.value = false
    }
  } else {
    popoverVisible.value = false
  }
}

let leaveTimer = null

// 处理单元格鼠标进入事件
const handleCellMouseEnter = ({ row, column, cell }) => {
  if (leaveTimer) {
    clearTimeout(leaveTimer)
    leaveTimer = null
  }

  // 检查当前列是否需要显示悬浮框
  if (!props.showColumns.includes(column.field)) {
    popoverVisible.value = false
    return
  }

  currentRowData.value = { ...row }

  const rect = cell.getBoundingClientRect()
  virtualElement.getBoundingClientRect = () => ({
    width: rect.width,
    height: rect.height,
    top: rect.top,
    left: rect.left,
    right: rect.right,
    bottom: rect.bottom,
    x: rect.left,
    y: rect.top
  })

  popoverVisible.value = true
}

// 处理单元格鼠标离开事件
const handleCellMouseLeave = ({ event }) => {
  if (!event) {
    popoverVisible.value = false
    return
  }

  leaveTimer = setTimeout(() => {
    const popoverEl = document.querySelector('.my-popover')
    if (popoverEl) {
      const popoverRect = popoverEl.getBoundingClientRect()
      const { clientX, clientY } = event

      // 检查鼠标是否在 popover 内
      if (
        !(
          clientX >= popoverRect.left &&
          clientX <= popoverRect.right &&
          clientY >= popoverRect.top &&
          clientY <= popoverRect.bottom
        )
      ) {
        popoverVisible.value = false
      }
    } else {
      popoverVisible.value = false
    }
  }, 200)
}

// 暴露方法给父组件
defineExpose({
  handleCellMouseEnter,
  handleCellMouseLeave
})

// 组件卸载时清理定时器
onUnmounted(() => {
  if (leaveTimer) {
    clearTimeout(leaveTimer)
    leaveTimer = null
  }
})
</script>

<style lang="scss" scoped>
.popover-content {
  max-height: 300px;
  overflow-y: auto;

  .popover-item {
    display: flex;
    padding: 6px 0;
    font-size: 12px;
    border-bottom: 1px dashed var(--el-border-color-lighter);

    &:hover {
      background-color: var(--el-fill-color-lighter);
    }

    &:last-child {
      border-bottom: none;
    }

    .item-label {
      font-weight: 600;
      margin-right: 10px;
      min-width: 100px;
      color: var(--el-text-color-secondary);
    }

    .item-value {
      flex: 1;
      word-break: break-all;
      color: var(--el-text-color-primary);
    }
  }
}

// 添加过渡动画
:deep(.el-popper) {
  transition:
    opacity 0.2s,
    transform 0.2s !important;
}

:deep(.el-popper.is-pure) {
  padding: 12px !important;
}
</style>
